package eiisan.threadsource;

import sun.misc.Unsafe;


/**
 * 参考 https://blog.csdn.net/itwxming/article/details/107520024
 *
 * @Auther: eii
 * @Date: 2020/9/21 10:16
 * @Description:
 */
public class TestCASUnSafe {

    private static Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
    /**
     * 普通变量
     */
    private static Integer number = 0;
    /**
     * Integer 中value的偏移量
     */
    private static long valueOffset = 0;

    static {
        try {
            //获取value的偏移量
            valueOffset = unsafe.objectFieldOffset(number.getClass().getDeclaredField("value"));
            System.out.println("偏移量为:" + valueOffset);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public static void change() {
        System.out.println("change before: number=" + number);
        //获取value的偏移量
        unsafe.compareAndSwapInt(number, valueOffset, 0, 1);
        unsafe.getAndAddInt(number, valueOffset, 1);
        System.out.println("change after: number=" + number);
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            while (number == 0) {
            }
            //number变化的话，才会执行这个 log，执行也就意味着可见
            System.out.println("线程thread1:" + Thread.currentThread().getName() + "发现number改变，跳出死循环");
        }, "thread1");
        thread1.start();

        Thread thread2 = new Thread(() -> {
            while (unsafe.getIntVolatile(number, valueOffset) == 0) {
            }
            //number变化的话，才会执行这个log，执行也就意味着可见
            System.out.println("线程thread2:" + Thread.currentThread().getName() + "发现number改变，跳出死循环");

        }, "thread2");
        thread2.start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //thread3只是改变number值0 -> 1
        Thread thread3 = new Thread(() -> {
            change();
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("change执行5秒之后啦，快看看thread1、thread2有没 有跳出死循环");
            }
        }, "thread3");
        thread3.start();
        System.out.println("程序结束");
    }
}
